/** ***************************************************************************
 * CoffeeSpriteBank.hpp
 * 2012 CoffeeParty Ltd.
 * Date Created: 2012-07-21                                  format YYYY-MM-DD
 * Revision Id: $Id$
 ******************************************************************************
 */

#ifndef _COFFEE_SPRITEBANK_HPP_
#define _COFFEE_SPRITEBANK_HPP_

struct SpriteFrame
{
    c_uint textureNum;
    c_uint rectNum;
};

struct SpriteCollection
{
    SpriteCollection() : frames(), frameTime(0) { }

    c_array<SpriteFrame> frames;
    c_uint frameTime;
};

class CoffeeSpriteBank
{
public:
    ~CoffeeSpriteBank()
    {
        for (c_uint i = 0; i < textures.size(); ++i)
            if (textures[i])
                drop(textures[i]);
    }

    c_array<c_rect<c_int> >& getPositions()
    {
        return texrects;
    }

    c_array<SpriteCollection>& getSprites()
    {
        return sprites;
    }

    c_uint getTextureCount() const
    {
        return textures.size();
    }

    CoffeeTexture* getTexture(c_uint index) const
    {
        if (index < textures.size())
            return textures[index];

        return 0;
    }

    c_void addTexture(CoffeeTexture* texture)
    {
        if (texture)
            textures.push_back(texture);
    }

    c_void setTexture(c_uint index, CoffeeTexture* texture)
    {
        while (index >= textures.size())
            textures.push_back(0);

        if (textures[index])
            drop(textures[index]);

        textures[index] = texture;
    }

    c_int addTextureAsSprite(CoffeeTexture* texture)
    {
        if (!texture)
            return -1;

        addTexture(texture);
        c_uint textureIndex = getTextureCount() - 1;
        c_uint rectangleIndex = texrects.size();

        texrects.push_back(c_rect<c_int>(0, 0, texture.getOriginalSize().x, textures.getOriginalSize().y));
        SpriteCollection tmpspr;
        tmpspr.frameTime = 0;

        SpriteFrame frame;
        frame.textureNum = textureIndex;
        frame.rectangleNum = rectangleIndex;

        tmpspr.frames.push_back(frame);
        sprites.push_back(tmpspr);
        return sprites.size() - 1;
    }

    c_void clear()
    {
        for (c_uint i = 0; i < textures.size(); ++i)
            if (textures[i])
                drop(textures[i]);

        textures.clear();
        sprites.clear();
        texrects.clear();
    }

    c_void draw2dSprite(c_uint index, const c_position<c_int>& pos,
        const c_rect<c_int>* clip = 0, const c_color& color = c_color(255, 255, 255, 255),
        c_uint startTime = 0, c_uint currentTime = 0, c_bool loop = true, c_bool center = false)
    {
        if (index >= sprites.size() || sprites[index].frames.empty() )
            return;

        c_uint frame = 0;
        if (sprites[index].frameTime)
        {
            c_uint f = ((currentTime - startTime) / sprites[index].frameTime);
            if (loop)
                frame = f % sprites[index].frames.size();
            else frame = (f >= sprites[index].frames.size()) ? sprites[index].frames.size()-1 : f;
        }

        const CoffeeTexture* tex = textures[sprites[index].frames[frame].textureNumber];
        if (!tex)
            return;

        const c_int rn = sprites[index].frames[frame].rectangleNum;
        if (rn >= rectangles.size())
            return;

        const c_rect<c_int>& r = rectangles[rn];

        if (center)
        {
            c_position<c_int> p = pos;
            p -= r.getSize() / 2;
            draw2DImage(tex, p, r, clip, color, true);
        }
        else draw2DImage(tex, pos, r, clip, color, true);
    }

protected:
    c_array<SpriteCollection> sprites;
    c_array<c_rect<c_int> > texrects;
    c_array<CoffeeTexture*> textures;

};

#endif /** _COFFEE_SPRITEBANK_HPP_ */
